package zsl.algo;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Vector;

import zsl.utils.TAInfo;
import zsl.utils.WordCount;
import zsl.utils.WordCountList;

public class TAAlgo {
	/*
	 * list in lists are in descending order
	 */
	public static ArrayList<WordCount> getTopK(int k, Vector<WordCountList> lists, TAInfo taInfo, boolean isCollectStepInfo ){
		int threshold = 0;
		ArrayList<WordCount> topK = new ArrayList<>(k);
	
//		int maxDepth = getMaxDepth(lists);
		int maxDepth = lists.get(0).size();
		WordCount wc;
		WordCount overAllwc;
		
		for (int i = 0; i < maxDepth; i++) {
			threshold = 0;
			for (WordCountList list : lists) {
				wc = list.get(i);
				threshold += wc.getCount();
				overAllwc = getOverAllCount(wc, lists);
				detectAndAddToTopK(overAllwc, topK, k);
			}
			
			if(isCollectStepInfo) taInfo.addStepInfos(i, threshold, topK.get(topK.size()-1).getCount());
			
			if (topK.size() == k && topK.get(k-1).getCount() >= threshold) {
				if (taInfo != null) {
					taInfo.setMaxDepth(maxDepth);
					taInfo.setAccessDepth(i);
				}
				break;
			}
		}
		return topK;
	}
	
	
	private static int getMaxDepth(Vector<WordCountList> lists){
		int curMaxDepth = lists.get(0).size();
		for (WordCountList wordCountList : lists) {
			if (wordCountList.size()>curMaxDepth) {
				curMaxDepth = wordCountList.size();
			}
		}
		return curMaxDepth;
	}
		
	private static void detectAndAddToTopK(WordCount wc, ArrayList<WordCount> topK, int k) {
		int size = topK.size();
		int count = wc.getCount();

		if (size == k && topK.get(size-1).getCount() >= count) {
			return;
		}
		
		boolean isSet = false;
		for (int i = 0; i < size; i++) {

			WordCount wordCount = topK.get(i);
			if (wordCount.getCount() == count) {
				if (wordCount.getWord().equals(wc.getWord())) {
					isSet = true;
					break;
				}else {
					continue;
				}
			}
			
			if (wordCount.getCount() < count) {
				topK.add(i, wc);
				isSet = true;
				break;
			}
			
		}
		
		if (!isSet) {
			topK.add(wc);
		}
		
		if (topK.size() > k) {
			topK.remove(topK.size()-1);
		}
	}
	
	private static WordCount getOverAllCount(WordCount wc, Vector<WordCountList> lists){
		int overAllCount = 0;
		String word = wc.getWord();
		for (WordCountList wordCountList : lists) {
			overAllCount += wordCountList.getCount(word);
		}
		return new WordCount(word, overAllCount);
	}
	
}
